#pragma once

#include <Windows.h>
#include <TlHelp32.h>

#include <memory>

#include "ProcessIterator.h"
#include "Process.h"
#include "ProcessWin.h"
#include "WinHandleDelete.h"

class ProcessIteratorWin : public ProcessIterator
{
public:
	ProcessIteratorWin();

	virtual const ProcessIterator& operator++()
	{
		if (first)
		{
			first = false;
			if (proc)
				return *this;
		}

		PROCESSENTRY32 info = {};
		info.dwSize = sizeof(info);
		HANDLE yohandle = 0;

		while (::Process32Next(th32handle.get(), &info) && 0 == (yohandle = ::OpenProcess(PROCESS_ALL_ACCESS, 0, info.th32ProcessID)))
			::CloseHandle(yohandle);

		if (yohandle)
		{
			proc = ProcessWin::fromHandleAndName(share_handle(yohandle), info.szExeFile);
			return *this;
		}

		proc.reset(); // set to 0
		return *this;
	}

	virtual explicit operator bool() const
	{
		return proc.get() != 0;
	}

	virtual ProcessPtr operator*()
	{
		return proc;
	}

	virtual ~ProcessIteratorWin()
	{

	}

protected:
	ProcessPtr proc;
	shared_handle th32handle;
	bool first;
};
